﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SerialPortTestSender
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private SerialPort _serialPort;
        private string[] _lines;
        private CancellationTokenSource _cts;

        public MainWindow()
        {
            InitializeComponent();
            comboBoxPorts.ItemsSource = SerialPort.GetPortNames();
        }

        private void BtnOpenPort_Click(object sender, RoutedEventArgs e)
        {
            if (_serialPort != null && _serialPort.IsOpen)
            {
                _serialPort.Close();
                _serialPort.Dispose();
            }

            _serialPort = new SerialPort(comboBoxPorts.Text, int.Parse(txtBaudRate.Text));
            _serialPort.Open();
            textBlockStatus.Text = $"串口 {comboBoxPorts.Text} 已打开";
        }
        private List<byte[]> _rawDataLines;
        private void BtnLoadFile_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new Microsoft.Win32.OpenFileDialog();
            if (dialog.ShowDialog() != true) return;

            try
            {
                // 读取为文本（假设是 UTF-8）
                string fileContent = File.ReadAllText(dialog.FileName);
                string[] lines = fileContent.Split(new[] { '\n' }, StringSplitOptions.None);

                _rawDataLines = new List<byte[]>();

                foreach (string line in lines)
                {
                    string trimmedLine = line.TrimEnd('\r'); // 去除行尾 \r
                    byte[] rawData = ParseEscapeString(trimmedLine); // ✅ 解析 \x1D 等转义符
                    _rawDataLines.Add(TrimSpaceBytes(rawData)); // 再去除首尾空格字节
                }

                textBlockStatus.Text = $"已加载 {_rawDataLines.Count} 行数据（支持转义字符）";
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载文件失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        // 清理 byte[] 首尾的空格（仅 ASCII 32）
        private byte[] TrimSpaceBytes(byte[] input)
        {
            if (input == null || input.Length == 0) return input;

            int start = 0;
            int end = input.Length - 1;

            while (start <= end && input[start] == 0x20) start++;

            while (end >= start && input[end] == 0x20) end--;

            int length = end - start + 1;
            if (length <= 0) return new byte[0];

            byte[] result = new byte[length];
            Array.Copy(input, start, result, 0, length);
            return result;
        }
        /// <summary>
        /// 将包含转义字符的字符串转换为字节数组（支持 \r \n \t \\ \xHH）
        /// </summary>
        private byte[] ParseEscapeString(string input)
        {
            if (string.IsNullOrEmpty(input)) return Array.Empty<byte>();

            var bytes = new List<byte>();
            for (int i = 0; i < input.Length; i++)
            {
                if (input[i] == '\\' && i + 1 < input.Length)
                {
                    switch (input[i + 1])
                    {
                        case 'r': bytes.Add(0x0D); i++; break;
                        case 'n': bytes.Add(0x0A); i++; break;
                        case 't': bytes.Add(0x09); i++; break;
                        case '\\': bytes.Add(0x5C); i++; break;
                        case 'x':
                            if (i + 3 < input.Length)
                            {
                                if (byte.TryParse(input.Substring(i + 2, 2), System.Globalization.NumberStyles.HexNumber, null, out byte hex))
                                {
                                    bytes.Add(hex);
                                    i += 3;
                                }
                                else
                                {
                                    bytes.Add((byte)'\\');
                                }
                            }
                            else
                            {
                                bytes.Add((byte)'\\');
                            }
                            break;
                        default:
                            bytes.Add((byte)'\\');
                            break;
                    }
                }
                else
                {
                    bytes.Add((byte)input[i]);
                }
            }
            return bytes.ToArray();
        }
        private async void BtnStartSend_Click(object sender, RoutedEventArgs e)
        {
            if (_serialPort == null || !_serialPort.IsOpen || _rawDataLines == null)
            {
                MessageBox.Show("请先加载数据文件并打开串口！");
                return;
            }

            int interval;
            if (!int.TryParse(txtInterval.Text, out interval) || interval < 0)
            {
                MessageBox.Show("请输入有效的发送间隔（毫秒）");
                return;
            }
            string suffixText = txtSuffix.Text;
            bool sendSuffix = chkSendSuffix.IsChecked == true;

            _cts = new CancellationTokenSource();

            try
            {
                await Task.Run(async () =>
                {
                    do
                    {
                        foreach (var rawData in _rawDataLines)
                        {
                            if (_cts.Token.IsCancellationRequested) return;

                            byte[] suffix = sendSuffix ? ParseEscapeString(suffixText) : Array.Empty<byte>();
                            byte[] sendData = new byte[rawData.Length + suffix.Length];

                            Buffer.BlockCopy(rawData, 0, sendData, 0, rawData.Length);
                            Buffer.BlockCopy(suffix, 0, sendData, rawData.Length, suffix.Length);

                            try
                            {
                                _serialPort.Write(sendData, 0, sendData.Length);

                                Application.Current.Dispatcher.Invoke(() =>
                                {
                                    string hex = BitConverter.ToString(sendData);
                                    listBoxLog.Items.Add($"已发送 HEX: {hex}");
                                    if (listBoxLog.Items.Count > 1000)
                                        listBoxLog.Items.RemoveAt(0);
                                    listBoxLog.ScrollIntoView(listBoxLog.Items[listBoxLog.Items.Count - 1]);
                                });

                                await Task.Delay(interval, _cts.Token);
                            }
                            catch (Exception ex) when (!(ex is OperationCanceledException))
                            {
                                Application.Current.Dispatcher.Invoke(() =>
                                {
                                    listBoxLog.Items.Add($"发送失败: {ex.Message}");
                                });
                                return;
                            }
                            catch (OperationCanceledException) { return; }
                        }
                    } while (chkLoop.IsChecked == true && !_cts.Token.IsCancellationRequested);
                }, _cts.Token);
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发送任务异常: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                _cts?.Cancel();
                _cts?.Dispose();
                _cts = null;
                textBlockStatus.Text = "已停止发送";
            }
        }
        private void BtnStopSend_Click(object sender, RoutedEventArgs e)
        {
            _cts?.Cancel();
        }
    }
}
